﻿#region

using System;
using System.Configuration;
using System.Reflection;
using EsbMonitorExtension.Config;
using EsbMonitorMessages.Domain;
using NServiceBus.Unicast;
using NServiceBus.Unicast.Transport.Msmq;
using NServiceBus.Utils;

#endregion

namespace EsbMonitorExtension
{
    public static class UnicastBusExtensions
    {

        public static Func<IUnicastBus, ServiceInfo> PrepareServiceInfoFunc = PrepareServiceInfo;

        public static ServiceInfo ServiceInfo(this IUnicastBus unicastBus)
        {
            return PrepareServiceInfoFunc(unicastBus);
        }

        private static ServiceInfo PrepareServiceInfo(IUnicastBus unicastBus)
        {
            ServiceDescriptionConfig serviceDescriptionConfig = GetServiceDescriptionConfig();

            string version = serviceDescriptionConfig != null ? serviceDescriptionConfig.Version ?? "1.0" : "1.0";
            string name = serviceDescriptionConfig != null ? serviceDescriptionConfig.Name ?? "" : "";
            string summary = serviceDescriptionConfig != null ? serviceDescriptionConfig.Summary ?? "" : "";

            InputQueueInfo inputQueue = unicastBus.InputQueue();
            InputQueueInfo errorQueue = unicastBus.ErrorQueue();
            InputQueueInfo auditQueue = unicastBus.AuditQueue();

            if (string.IsNullOrEmpty(name))
            {
                name = inputQueue.QueueName;
            }


            return new ServiceInfo(name, summary, version, inputQueue, errorQueue, auditQueue);
        }

        public static InputQueueInfo InputQueue(this IUnicastBus unicastBus)
        {
            MsmqTransport transport = ReadTransport(unicastBus);

            if (transport != null)
            {
                String address = transport.Address;
                String fullAddress = MsmqUtilities.GetFullPathWithoutPrefix(address);
                return new InputQueueInfo(fullAddress);
            }

            return null;
        }

        public static InputQueueInfo ErrorQueue(this IUnicastBus unicastBus)
        {
            MsmqTransport transport = ReadTransport(unicastBus);

            if (transport != null)
            {
                String address = transport.ErrorQueue;

                if (address == null)
                {
                    return null;
                }

                String fullAddress = MsmqUtilities.GetFullPathWithoutPrefix(address);
                return new InputQueueInfo(fullAddress);
            }

            return null;
        }

        public static InputQueueInfo AuditQueue(this IUnicastBus unicastBus)
        {
            UnicastBus plainUnicastBus = (UnicastBus) unicastBus;

            String address = plainUnicastBus.ForwardReceivedMessagesTo;

            if (string.IsNullOrEmpty(address))
            {
                return null;
            }

            String fullAddress = MsmqUtilities.GetFullPathWithoutPrefix(plainUnicastBus.ForwardReceivedMessagesTo);

            return new InputQueueInfo(fullAddress);
        }


        private static MsmqTransport ReadTransport(IUnicastBus unicastBus)
        {
            FieldInfo t = typeof (UnicastBus).GetField("transport",
                                                       BindingFlags.Public | BindingFlags.NonPublic |
                                                       BindingFlags.Instance);

            return t.GetValue(unicastBus) as MsmqTransport;
        }

        public static ServiceDescriptionConfig GetServiceDescriptionConfig()
        {
            return ConfigurationManager.GetSection(typeof (ServiceDescriptionConfig).Name) as ServiceDescriptionConfig;
        }
    }
}